/**
 * 
 */
package com.celephais.common.client.model;

import java.util.List;

import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.rpc.IsSerializable;

/**
 * @author Eugene Shen
 * All objects that wants to use the automated ObjectAccessService
 * framework needs to implement this interface.
 */
public interface TransferObject extends IsSerializable {
	
	/**
	 * Return an array of the columns of this object.  Basically, meta-data.
	 * Highly recommended to just return a static array.
	 * @return An array of all the columns on this object.
	 */
	public TableColumn[] getColumns();
	
	/**
	 * Returns the string representation of the key of this object.
	 * @return The key of this object.
	 */
	public String getKey();
	
	/**
	 * Returns the name of this object.
	 * @return The name of this object.
	 */
	public String getName();
	
	/**
	 * Return the value of a column, given the column name.
	 * @param columnName The name of the column to fetch the value for.
	 * @return The value of that field / column.
	 */
	public String getValue(String columnName);
	
	/**
	 * Sets the value of a column, given the name and new value.
	 * @param columnName The name of the column to set.
	 * @param value The new value for the given column.
	 */
	public void setValue(String columnName, String value);
	
	// THE FOLLOWING 3 METHODS DEAL WITH REFERENCES.  YOU ONLY NEED TO
	// WORRY ABOUT THEM IF YOU HAVE REFERENCE TYPES ON YOUR OBJECT.
	
	/**
	 * Return the reference object associated with columnName.
	 * You ONLY need to worry about this method if one of your columns
	 * is a Reference type.  This method will only be invoked on Reference
	 * type columns.
	 * @param columnName The Reference type column to obtain the reference
	 *                   object for.
	 * @return The associated reference object.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public ReferenceUI getReference(String columnName)
			throws UnimplementedException;
	
	/**
	 * Sets the reference object of a Reference type column.
	 * You ONLY need to worry about this method if one of your columns
	 * is a Reference type.  This method will only be invoked on Reference
	 * type columns.
	 * @param columnName The name of the Reference type column to set.
	 * @param ref The reference object to assign to the given column.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public void setReference(String columnName, ReferenceUI ref)
			throws UnimplementedException;
	
	/**
	 * Returns a list of possible reference values that can be set for the
	 * given column.  Unlike every other method on this interface,
	 * THIS ONE IS ACTUALLY ASYNCHRONOUS because it will typically involve
	 * a service call.
	 * You ONLY need to worry about this method if one of your columns
	 * is a Reference type.  This method will only be invoked on Reference
	 * type columns.
	 * @param columnName The column to obtain a list of valid values for.
	 * @param callback The list of valid TransferObjects that can be used as
	 *         references for this field.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public void listValidReferences(String columnName, AsyncCallback<List<? extends TransferObject>> callback)
			throws UnimplementedException;
	
	// THE FOLLOWING 5 METHODS DEAL WITH CHILDREN.  YOU ONLY NEED TO WORRY
	// ABOUT THEM IF YOU HAVE CHILDREN (OWNED) OBJECTS.
	
	/**
	 * Returns the list of child objects corresponding to this column.
	 * You ONLY need to worry about this method if one of your columns is a
	 * Child type.  This method will only be invoked on Child type columns.
	 * @param columnName The name of the Child type column to fetch.
	 * @return The list of child objects corresponding to the column.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public List<? extends TransferObject> getChildren(String columnName)
			throws UnimplementedException;
	
	/**
	 * Returns a new instance of a child object that can be contained in
	 * this column.  This method will only be invoked on Child type columns.
	 * @param columnName The child-type column to obtain a new child for.
	 * @return A new instance of the child object.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public TransferObject createChild(String columnName)
			throws UnimplementedException;
	
	/**
	 * Adds a child at the specified position.  newChild should have been
	 * obtained via createChild, but double-check its class just to be sure.
	 * This method will only be invoked on Child type columns.  
	 * @param columnName The child column to add a child.
	 * @param position The position where the child should be added.
	 *                 IF NEGATIVE, add to end of list.
	 * @param newChild The new child object to add.
	 * @return Whether or not the add was successful.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public boolean addChild(String columnName, int position,
				TransferObject newChild) throws UnimplementedException;
	
	/**
	 * Removes a child at the specified position.
	 * This method will only be invoked on Child type columns.
	 * @param columnName The child-collection column to remove items from.
	 * @param position The position of the child that needs to be removed.
	 * @return Whether or not the remove was successful.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public boolean removeChild(String columnName, int position)
			throws UnimplementedException;
	
	/**
	 * Moves a child from one position to another.
	 * This method will only be invoked on Child type columns.
	 * @param columnName The child-collection column where the to-be-moved
	 *                   child resides.
	 * @param oldPosition The current position of the child.
	 * @param newPosition The new position of the child.  The child will be
	 *                    moved to the end if this value is either negative
	 *                    or >= the number of children in this column.
	 * @return Whether or not the move was successful.
	 * @throws UnimplementedException This exception should only be thrown
	 *         by base classes that expect child classes to implement this
	 *         method as necessary.
	 */
	public boolean moveChild(String columnName, int oldPosition,
			int newPosition) throws UnimplementedException;
}
